/**
 * 给一个树，定义 Di = SIGMA{max(Au, Av) * |Au - Av|, u、v是i子树中的点}
 * 求所有Di的异或和，可以自然溢出。
 * 树上启发式合并，使用三个权值树状数组
 * Bcnt记录权值的数量，Bsum记录权值的和，B2记录权值的平方和
 * 
 * 前面是正常的dsuontree流程
 * 
 * 令 Du += D[所有儿子]
 * 统计u节点时，对u的每个轻儿子:
 *     对每个节点i:
 *         令j是i的就编号 w = Wj
 *         查询树状数组, 令c是比w小的数量，s是小的权值和
 *         则 Du += (c * w - sum) * 2 * w
 *         再查，令s是比w大的权值和，s2是比w大平方和
 *         则 Du += (s2 - w * s) * w
 *     for每个节点i: 
 *         利用w更新树状数组
 * 统计u节点本身
 * 
 * 如果无需keep：
 *    for u子树的所有节点：
 *        反向更新树状数组
 */
#include <bits/stdc++.h>
using namespace std;
#include <bits/extc++.h>
using namespace __gnu_pbds;

using llt = long long;
using vi = vector<int>;
using vll = vector<llt>;

using value_type = unsigned long long;

int LIMIT;

struct FenwickTree{ // 树状数组

using value_type = ::value_type;
using vec_type = vector<value_type>;

int n;
vec_type c;

FenwickTree() = default;

static int lowbit(int x){return x & -x;}

void init(int nn){this->c.assign((this->n=nn) + 1, 0);}

void modify(int pos, value_type delta){
    for(int i=pos;i<=this->n;i+=lowbit(i)) this->c[i] += delta;
}

value_type query(int pos)const{
    value_type ans = 0;
    for(int i=pos;i;i-=lowbit(i)) ans += this->c[i];
    return ans;
}

value_type query(int s, int e)const{return this->query(e) - this->query(s - 1);}

};

FenwickTree Bcnt, Bsum, B2;

struct dsu_on_tree_t{ // init，输入数据，依次调用dfsHeavy(root, 0), dfs(root, 0, false)

using vi = vector<int>;

int N;
vector<vi> G; // 树, 1-index

struct node_t{ // 树链剖分的结构
    int size; 
    int hson; // 重儿子，这里是原树编号    
    int nid;  // 在树链剖分中的新编号
    int mdes; // 本子树全部在[nid, mdes]之间, 这是剖分编号
};
vector<node_t> Nodes;
vi New2Old;   // 剖分的编号为i，则原树节点编号为New2Old[i], 显然有Nodes[New2Old[i]].nid == i
int TimeStamp;
int Root;

unsigned long long Ans;
vector<value_type> W; 
vector<value_type> D;

void init(int n){
    N = n;
    G.assign(N + 1, {});
    Nodes.assign(N + 1, {0, 0, 0, 0});
    New2Old.assign(N + 1, 0);
    TimeStamp = 0;
    W.assign(N + 1, 0ULL);
	Ans = 0;
	D.assign(N + 1, 0ULL);
}

void mkDiEdge(int a, int b){
    G[a].push_back(b);
}

void mkBiEdge(int a, int b){
    mkDiEdge(a, b);
    mkDiEdge(b, a);
}

void dfsHeavy(int u, int p){ // 递归重儿子
    auto & n = Nodes[u];
    n.size = 1;
    New2Old[n.nid = ++TimeStamp] = u;

    for(auto v : G[u]){
        if(v == p) continue;

        dfsHeavy(v, u);
        n.size += Nodes[v].size;
        if(Nodes[n.hson].size < Nodes[v].size) n.hson = v;
    }

    n.mdes = TimeStamp;
    return;
}


void dfs(int u, int p, bool keep){ // 递归
    const auto & n = Nodes[u];
	D[u] = 0;

    for(auto v : G[u]){
        if(v == p or v == n.hson) continue;
        dfs(v, u, false);
		D[u] += D[v];
    }
    /// 最后递归重儿子
    if(n.hson) {
		dfs(n.hson, u, true);
		D[u] += D[n.hson];
	}

    for(auto v : G[u]){
		if(v == p or v == n.hson) continue;

		for(int j,i=Nodes[v].nid;i<=Nodes[v].mdes;++i){
            j = New2Old[i];
			auto c = Bcnt.query(W[j] - 1);
			auto sum = Bsum.query(W[j] - 1);
			D[u] += (c * W[j] - sum) * 2 * W[j];

			sum = Bsum.query(W[j] + 1, LIMIT);
			auto s2 = B2.query(W[j] + 1, LIMIT);
			D[u] += (s2 - sum * W[j]) * 2; 
		}

		for(int j, i=Nodes[v].nid;i<=Nodes[v].mdes;++i){
            j = New2Old[i];
            Bcnt.modify(W[j], 1);
			Bsum.modify(W[j], W[j]);
            B2.modify(W[j], W[j] * W[j]);
		}
	}

    auto c = Bcnt.query(W[u] - 1);
	auto sum = Bsum.query(W[u] - 1);
    D[u] += (c * W[u] - sum) * 2 * W[u];

	sum = Bsum.query(W[u] + 1, LIMIT);
    auto s2 = B2.query(W[u] + 1, LIMIT);
	D[u] += (s2 - sum * W[u]) * 2;

	Bcnt.modify(W[u], 1);
	Bsum.modify(W[u], W[u]);
    B2.modify(W[u], W[u] * W[u]);

#ifndef ONLINE_JUDGE
    // cout << u << ", " << (llt)D[u] << endl;
	// for(int i=1;i<LIMIT;++i){
	// 	cout << "value " << i << ", " << (long long)Bcnt.query(i, i) << endl;
	// }
#endif

    Ans ^= D[u];

    /// 是否清空u子树对即时数据的影响
    if(not keep){
        for(int j,i=n.nid;i<=n.mdes;++i){
            j = New2Old[i];
            Bcnt.modify(W[j], -1);
			Bsum.modify(W[j], -W[j]);
            B2.modify(W[j], -W[j] * W[j]);
        }
    }
    return;
}


};

int N;
dsu_on_tree_t Tree;
vector<unsigned long long> W;


void work(){
    cin >> N;
	Tree.init(N);
	for(int a,b,i=1;i<N;++i){
		cin >> a >> b;
		Tree.mkBiEdge(a, b);
	}
	for(int i=1;i<=N;++i) {
        int t; cin >> t;
		Tree.W[i] = t;
		LIMIT = max(LIMIT, t);
	}
	LIMIT += 1;
	
	Bcnt.init(LIMIT);
	Bsum.init(LIMIT);
    B2.init(LIMIT);
	Tree.dfsHeavy(1, 0);
	Tree.dfs(1, 0, true);
	cout << Tree.Ans << endl;
	return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--) work();
	return 0;
}